package com.starlink.service.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.hutool.core.convert.Convert;
import com.github.pagehelper.PageInfo;
import com.github.pagehelper.PageHelper;
import com.starlink.context.SessionContext;
import com.starlink.mapper.UserMapper;
import com.starlink.model.domain.StarPaintDO;
import com.starlink.model.domain.UserDO;
import com.starlink.model.request.PointsAcquireBillRequest;
import com.starlink.model.request.PointsUseBillRequest;
import com.starlink.model.vo.PointsVO;
import com.starlink.model.vo.StarPaintVO;
import com.starlink.service.PointsService;
import com.starlink.service.StarPaintService;
import org.springframework.data.domain.Pageable;
import com.starlink.common.utils.AssertUtil;
import com.starlink.model.dtomapper.StarPaintRegisterDtoMapper;
import com.starlink.model.domain.StarPaintRegisterDO;
import com.starlink.mapper.StarPaintRegisterMapper;
import com.starlink.model.request.StarPaintRegisterRequest;
import com.starlink.service.StarPaintRegisterService;
import com.starlink.model.util.StarPaintRegisterConvert;
import com.starlink.model.vo.StarPaintRegisterVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import static com.starlink.common.enums.AcquireModeEnum.POINT_XIAO_FEI;
import static com.starlink.common.enums.AcquireModeEnum.TUI_KUAN;
import static com.starlink.common.enums.ActionTypeEum.*;
import static com.starlink.utils.PageUtils.getOrderBy;

import java.util.Date;
import java.util.List;
import java.util.Optional;

/**
 * @author zhanghong
 */
@Service
public class StarPaintRegisterServiceImpl extends ServiceImpl<StarPaintRegisterMapper, StarPaintRegisterDO> implements StarPaintRegisterService {
    @Autowired
    private StarPaintRegisterMapper starPaintRegisterMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private StarPaintService starPaintService;
    @Autowired
    private PointsService pointsService;

    @Override
    public StarPaintRegisterVO getByKey(long id) {
        StarPaintRegisterVO starPaintRegisterVO = StarPaintRegisterDtoMapper.INSTANCE.do2VO(getById(id));
        return starPaintRegisterVO;
    }

    @Override
    public PageInfo<StarPaintRegisterVO> pageQuery(Pageable pageable,StarPaintRegisterRequest request) {
        PageHelper.startPage(request.getPageNum(), request.getPageSize(), getOrderBy(pageable.getSort())).setReasonable(true);
        List<StarPaintRegisterDO> list = starPaintRegisterMapper.listQuery(request);
        List<StarPaintRegisterVO> starPaintRegisterVOList = StarPaintRegisterConvert.buildStarPaintRegisterVoList(list);
        for (StarPaintRegisterVO item : starPaintRegisterVOList) {
            // 查询用户
            UserDO userDO = userMapper.selectDOById(item.getUserId());
            if (userDO != null) {
                item.setUserNickName(userDO.getNickName());
                item.setUserRealName(userDO.getRealName());
                item.setMobile(userDO.getMobile());
                item.setAvatar(userDO.getAvatar());
            }
            // 查询活动
            item.setStarPaintVO(starPaintService.getByKey(item.getStarPaintId()));
        }
        return new PageInfo(starPaintRegisterVOList);
    }

    @Override
    public List<StarPaintRegisterVO> listQuery(StarPaintRegisterRequest request) {
        List<StarPaintRegisterDO> list = starPaintRegisterMapper.selectDOList(StarPaintRegisterDtoMapper.INSTANCE.request2DO(request));
        List<StarPaintRegisterVO> starPaintRegisterVOS = StarPaintRegisterConvert.buildStarPaintRegisterVoList(list);
        return starPaintRegisterVOS;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean add(StarPaintRegisterRequest request) {
        AssertUtil.assertNotNull(request.getStarPaintId(), "星阅绘活动id不能为空");
        StarPaintVO starPaintVO = starPaintService.getByKey(request.getStarPaintId());
        AssertUtil.assertNotNull(starPaintVO, "星阅绘活动不存在");
        AssertUtil.assertTrue(DateUtil.isIn(new Date(), starPaintVO.getSignStartTime(), starPaintVO.getSignEndTime()), "当前时间不是报名时间范围");
        request.setUserId(SessionContext.getWechatUserId());
        if (starPaintVO.getLimitNum() != -1) {
            Long count = lambdaQuery().eq(StarPaintRegisterDO::getStarPaintId, request.getStarPaintId()).count();
            AssertUtil.assertTrue(count <= starPaintVO.getLimitNum(), "报名已达上限");
        }
        if (starPaintVO.getConsumePoints() != null && starPaintVO.getConsumePoints() > 0) {
            PointsVO pointsVO = pointsService.selectPointInfo(request.getUserId());
            AssertUtil.assertTrue(pointsVO.getAvailablePoints() >= starPaintVO.getConsumePoints(), "积分不足,报名失败");
            // 扣除积分
            PointsUseBillRequest billRequest = new PointsUseBillRequest();
            billRequest.setUserId(request.getUserId());
            billRequest.setTitle(JOIN_STAR_PAINT_ACTIVITY.getType());
            billRequest.setConsumeMode(POINT_XIAO_FEI.getType());
            billRequest.setConsumePonts(starPaintVO.getConsumePoints());
            pointsService.consumPoint(billRequest);
        }

        save(StarPaintRegisterDtoMapper.INSTANCE.request2DO(request));
        return true;
    }


    @Async
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void returnPoints(StarPaintDO starPaintDO) {
        // 当前是由商家状态改为下架状态(活动进行或者活动未开始)
        long time = new Date().getTime();
        if (starPaintDO.getActivityEndTime().getTime() > time) {
            return;
        }
        if (starPaintDO.getConsumePoints() == 0) {
            return;
        }
        // 退还积分
        List<StarPaintRegisterDO> list = lambdaQuery().eq(StarPaintRegisterDO::getStarPaintId, starPaintDO.getId()).list();
        for (StarPaintRegisterDO item : list) {
            PointsAcquireBillRequest billRequest = new PointsAcquireBillRequest();
            billRequest.setUserId(item.getUserId());
            billRequest.setTitle(JOIN_STAR_PAINT_ACTIVITY.getType());
            billRequest.setAcquireMode(STAR_PAINT_ACTIVITY_CANCEL.getType());
            billRequest.setAcquirePoint(starPaintDO.getConsumePoints());
            pointsService.addPoint(billRequest);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateByKey(StarPaintRegisterRequest request) {
        AssertUtil.assertNotNull(request.getId(), "id不能为空");
        saveOrUpdate(StarPaintRegisterDtoMapper.INSTANCE.request2DO(request));
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteDOByIds(String ids) {
        starPaintRegisterMapper.deleteDOByIds(Convert.toStrArray(ids));
        return true;
    }
}
